#import "BWColorsetDocument.h"

#import "BWColorset.h"
#import "BWThreadColor.h"
#import "BWColorInspector.h"

@implementation BWColorsetDocument


- (id) init
{
    if (self = [super init]) {
        colorset = [[BWColorset alloc] init];
    }

    return (self);

} // init

- (void) awakeFromNib
{
    NSTableColumn *column;

    column = [[colorView tableColumns] objectAtIndex: 1];
    [column setDataCell: 
                [[[NSImageCell alloc] init] autorelease]];
    [column setEditable: NO];

    column = [[colorView tableColumns] objectAtIndex: 0];
    [column setEditable: NO];
    column = [[colorView tableColumns] objectAtIndex: 2];
    [column setEditable: NO];


    if ([colorset manufacturerName] != nil) {
        [manufacturerField setStringValue: [colorset manufacturerName]];
    }


} // awakeFromNib


- (NSString *) windowNibName
{
    return (@"BWColorsetDocument");
} // windowNibName



- (IBAction) updateManufacturerName: (id) sender
{
    [colorset setManufacturerName: [manufacturerField stringValue]];
    
} // updateManufacturerName



- (IBAction) newColor: (id) sender
{
    BWThreadColor *color;
    color = [[BWThreadColor alloc] init];

    [colorset addColor: color];

    [color autorelease];

    [colorView reloadData];
    [colorView selectRow: [colorset count] - 1
               byExtendingSelection: NO];
    [colorView scrollRowToVisible: [colorset count] - 1];

} // newColor



- (int) numberOfRowsInTableView: (NSTableView *) tableView
{
    return ([colorset count]);
} // numberOfRowsInTableView


- (id) tableView: (NSTableView *) tableView  objectValueForTableColumn: (NSTableColumn *) tableColumn  row: (int) row
{
    BWThreadColor *color;
    color = [colorset colorAtIndex: row];

    id value;

    if ([[tableColumn identifier] isEqualTo: @"color"]) {
        NSRect rect;
        rect.origin = NSZeroPoint;
        rect.size = NSMakeSize ([tableColumn width], 
                                [colorView rowHeight]);

        NSView *colorSwatch;
        colorSwatch = [[NSImage alloc] initWithSize: rect.size];

        [colorSwatch lockFocus];
        [[color color] set];

        [NSBezierPath fillRect: rect];
        [colorSwatch unlockFocus];

        [colorSwatch autorelease];
        
        value = colorSwatch;

    } else {
        value = [color valueForKey: [tableColumn identifier]];
    }

    return (value);

} // objectValueForTableColumn



- (void) tableViewSelectionDidChange: (NSNotification *) notification
{
    int row;
    row = [colorView selectedRow];

    BWThreadColor *color = nil;

    if (row != -1) {
        color = [colorset colorAtIndex: row];
    }

    BWColorInspector *inspector;
    inspector = [BWColorInspector defaultInspector];

    [inspector setCurrentDocument: self];
    [inspector setCurrentColor: color];

} // tableViewSelectionDidChange


- (void) colorChanged: (BWThreadColor *) color
{
    [colorView reloadData];
} // colorChanged



- (NSData *) dataRepresentationOfType: (NSString *) aType
{
    NSData *data;
    data = [NSArchiver archivedDataWithRootObject: colorset];

    return (data);

} // dataRepresentationOfType



- (BOOL) loadDataRepresentation: (NSData *) data
                         ofType: (NSString *) aType
{
    [colorset release];
    colorset = [NSUnarchiver unarchiveObjectWithData: data];
    [colorset retain];

    return (YES);

} // loadDataRepresentationOfType



- (void) splitLine: (char *) buffer  // will get modified
            length: (int) length
             mfrId: (char **) mfrId
              name: (char **) name
               red: (int *) red
             green: (int *) green
              blue: (int *) blue
{
    char *scan;

    // format is:
    // ID, name (can contain spaces) R G B  0xRGB

    scan = buffer;

    // skip any leading whitespace
    while (isspace(*scan)) {
        scan++;
    }

    // pick up the ID first
    *mfrId = scan;
    while (!isspace(*scan)) {
        scan++;
    }
    *scan++ = '\0';

    // skip any intervening whitespace
    while (isspace(*scan)) {
        scan++;
    }

    *name = scan;

    // now work backwards from the end picking off numbers.
    // when we're done, we'll be at the end of the name.

    scan = buffer + length - 1; // point to last char
    
    // just ignore the hex stuff
    while (!isspace(*scan)) {
        scan--;
    }

    while (isspace(*scan)) {
        *scan = '\0';
        scan--;
    }
    
    // back up over last number
    while (!isspace(*scan)) {
        scan--;
    }
    
    int colors[3], i;

    for (i = 0; i < 3; i++) {
    
        // eat any whitespace.  zero it out to terminate the numbers
        // when we get to it
        // later, rinse, repeat
        
        while (isspace(*scan)) {
            *scan = '\0';
            scan--;
        }
        
        // back up over last number
        while (!isspace(*scan)) {
            scan--;
        }
        colors[i] = atoi(scan);
    }
    *red = colors[2];
    *green = colors[1];
    *blue = colors[0];

    // eat up any remaining white space
    while (isspace(*scan)) {
        *scan = '\0';
        scan--;
    }

} // splitLine


- (BWThreadColor *) buildColorFromBuffer: (char *) buffer
                            length: (int) length
{
    BWThreadColor *color = nil;
    char *scan, *stop;

    // skip comment lines
    if (*buffer == '#') {
        goto bailout;
    }

    // skip whitespace-only lines
    BOOL onlyWhitespace = YES;

    scan = buffer;
    stop = scan + length;

    while (scan < stop) {
        if (isgraph(*scan)) {
            onlyWhitespace = NO;
            break;
        }
        scan++;
    }

    if (onlyWhitespace) {
        goto bailout;
    }
    
    // ok, we have a line.  pull it apart
    // assumes the line itself is fundamentally valid

    char *name, *mfrId;
    int red, green, blue;
    [self splitLine: buffer 
          length: length
          mfrId: &mfrId
          name: &name
          red: &red
          green: &green
          blue: &blue];

    color = [[BWThreadColor alloc] init];
    [color setManufacturerID: [NSString stringWithCString: mfrId]];
    [color setName: [NSString stringWithCString: name]];
    [color setColor: [NSColor colorWithCalibratedRed: (float)red / 255.0
                              green: (float)green / 255.0
                              blue: (float)blue / 255.0
                              alpha: 1.0]];
bailout:
    return (color);

} // buildColorsFromBuffer


- (IBAction) import: (id) sender
{
    FILE *file;
    file = fopen ("/Users/markd/Development/Borkware/BorkStitch/ColorsetEdit/dmcvalues.txt", "r");

    char buffer[4096];

    while (fgets(buffer, 4096, file)) {
        BWThreadColor *color;
        color = [self buildColorFromBuffer: buffer
                      length: strlen(buffer)];
        if (color != nil) {
            [colorset addColor: color];
        }
    }

    [colorView reloadData];

} // import


- (IBAction) remove: (id) sender
{
    int row;
    row = [colorView selectedRow];

    [colorset removeColorAtIndex: row];

    [colorView reloadData];
    [self tableViewSelectionDidChange: nil];

} // remove


- (void) tableView: (NSTableView *) tableView  didClickTableColumn: (NSTableColumn *) tableColumn
{
    if (lastSortColumn == tableColumn) {
        // clicked same column, change the sort order
        sortDescending = !sortDescending;

    } else {
        sortDescending = NO;
        if (lastSortColumn != nil) {
            [tableView setIndicatorImage: nil
                       inTableColumn: lastSortColumn];
            [lastSortColumn release];
        }
        lastSortColumn = tableColumn;
        [lastSortColumn retain];
        [tableView setHighlightedTableColumn: tableColumn];
    }

    // sort.  we can optimize and reverse the return from the
    // data source, but I'm lazy

    NSImage *indicatorImage;

    if (sortDescending) {
        indicatorImage = [NSImage imageNamed: @"NSAscendingSortIndicator"];
    } else {
        indicatorImage = [NSImage imageNamed: @"NSDescendingSortIndicator"];
    }

    [tableView setIndicatorImage: indicatorImage
               inTableColumn: tableColumn];

    // sample code on cocoadev builds a selector name, and
    // uses that.
    if ([[tableColumn identifier] isEqualTo: @"manufacturerID"]) {
        [colorset sortByManufacturerId: !sortDescending];

    } else if ([[tableColumn identifier] isEqualTo: @"color"]) {
        [colorset sortByColor: !sortDescending];

    } else if ([[tableColumn identifier] isEqualTo: @"name"]) {
        [colorset sortByName: !sortDescending];
    }
    
    [tableView reloadData];

} // didClickTableColumn


@end // BWColorsetDocument

